`include "define.v"


module ex_mem(

	input	wire										clk,
	input wire										rst,
	
	input wire[`RegAddrBus]       ex_wd,
	input wire                    ex_wreg,
	input wire[`RegBus]					 ex_wdata,

	input wire	ex_hilo_write_enable_i,
	input wire[`RegBus]	ex_hi,
	input wire[`RegBus] ex_lo,
	input wire[`StallBus] if_stall,

	input wire[`AluOpBus]        ex_aluop,
	input wire[`RegBus]          ex_mem_addr,
	input wire[`RegBus]          ex_reg2,

	input wire                   ex_cp0_reg_we,
	input wire[4:0]              ex_cp0_reg_write_addr,
	input wire[`RegBus]          ex_cp0_reg_data,	
	input wire[31:0]             ex_excepttype,
	input wire                   ex_is_in_delayslot,
	input wire[`RegBus]          ex_current_inst_address,
	input wire                   flush,

	output reg mem_hilo_write_enable_o,
	output reg[`RegBus]	mem_hi,
	output reg[`RegBus] mem_lo,
 	
	output reg[`RegAddrBus]      mem_wd,
	output reg                   mem_wreg,
	output reg[`RegBus]					 mem_wdata,

	input wire[`DoubleRegBus] hilo_i,
	input wire[1:0] cnt_i,

	output reg[`AluOpBus]        mem_aluop,
	output reg[`RegBus]          mem_mem_addr,
	output reg[`RegBus]          mem_reg2,

	output reg                   mem_cp0_reg_we,
	output reg[4:0]              mem_cp0_reg_write_addr,
	output reg[`RegBus]          mem_cp0_reg_data,

	output reg[`DoubleRegBus] hilo_o,
	output reg[1:0] cnt_o,
	output reg[`RegBus]          mem_addr_o,
	output wire					 mem_we_o,
	output reg[3:0]              mem_sel_o,
	output reg[`RegBus]          mem_data_o,
	output reg                   mem_ce_o,
	output reg[31:0]             mem_excepttype,
  	output reg                   mem_is_in_delayslot,
	output reg[`RegBus]          mem_current_inst_address

);


	always @ (posedge clk) begin
		if(rst == `RstEnable) begin
			mem_wd <= `NOPRegAddr;
			mem_wreg <= `WriteDisable;
		  	mem_wdata <= `ZeroWord;	
			mem_hilo_write_enable_o <= `WriteDisable;
			mem_hi <= `ZeroWord;
			mem_lo <= `ZeroWord;
			hilo_o <= {`ZeroWord, `ZeroWord};
			cnt_o <= 2'b00;	
			mem_aluop <= `EXE_NOP_OP;
			mem_mem_addr <= `ZeroWord;
			mem_reg2 <= `ZeroWord;	
			mem_cp0_reg_we <= `WriteDisable;
			mem_cp0_reg_write_addr <= 5'b00000;
			mem_cp0_reg_data <= `ZeroWord;	
			mem_excepttype <= `ZeroWord;
			mem_is_in_delayslot <= `NotInDelaySlot;
	    	mem_current_inst_address <= `ZeroWord;	
		end else begin
			if (flush == 1'b1) begin
				mem_wd <= `NOPRegAddr;
				mem_wreg <= `WriteDisable;
				mem_wdata <= `ZeroWord;
				mem_hi <= `ZeroWord;
				mem_lo <= `ZeroWord;
				mem_hilo_write_enable_o <= `WriteDisable;
				mem_aluop <= `EXE_NOP_OP;
				mem_mem_addr <= `ZeroWord;
				mem_reg2 <= `ZeroWord;
				mem_cp0_reg_we <= `WriteDisable;
				mem_cp0_reg_write_addr <= 5'b00000;
				mem_cp0_reg_data <= `ZeroWord;
				mem_excepttype <= `ZeroWord;
				mem_is_in_delayslot <= `NotInDelaySlot;
				mem_current_inst_address <= `ZeroWord;
				hilo_o <= {`ZeroWord, `ZeroWord};
				cnt_o <= 2'b00;	   
			end else if (if_stall[`STALL_EX] == `NoStop) begin
				mem_wd <= ex_wd;
				mem_wreg <= ex_wreg;
				mem_wdata <= ex_wdata;
				mem_hilo_write_enable_o <= ex_hilo_write_enable_i;
				mem_hi <= ex_hi;
				mem_lo <= ex_lo;

				hilo_o <= {`ZeroWord, `ZeroWord};
				cnt_o <= 2'b00;
				mem_aluop <= ex_aluop;
				mem_mem_addr <= ex_mem_addr;
				mem_reg2 <= ex_reg2;
				mem_cp0_reg_we <= ex_cp0_reg_we;
				mem_cp0_reg_write_addr <= ex_cp0_reg_write_addr;
				mem_cp0_reg_data <= ex_cp0_reg_data;

				mem_excepttype <= ex_excepttype;
				mem_is_in_delayslot <= ex_is_in_delayslot;
				mem_current_inst_address <= ex_current_inst_address;	
			end else if (if_stall[`STALL_EX] == `Stop && if_stall[`STALL_MEM] == `NoStop) begin
				mem_wd <= `NOPRegAddr;
				mem_wreg <= `WriteDisable;
				mem_wdata <= `ZeroWord;
				mem_hi <= `ZeroWord;
				mem_lo <= `ZeroWord;
				mem_hilo_write_enable_o <= `WriteDisable;
				hilo_o <= hilo_i;
				cnt_o <= cnt_i;

				mem_aluop <= `EXE_NOP_OP;
				mem_mem_addr <= `ZeroWord;
				mem_reg2 <= `ZeroWord;	
				mem_cp0_reg_we <= `WriteDisable;
				mem_cp0_reg_write_addr <= 5'b00000;
				mem_cp0_reg_data <= `ZeroWord;	
				mem_excepttype <= `ZeroWord;
				mem_is_in_delayslot <= `NotInDelaySlot;
				mem_current_inst_address <= `ZeroWord;	
			end else begin
				hilo_o <= hilo_i;
				cnt_o <= cnt_i;
			end
		end    //if
	end      //always
			

endmodule